home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
The World of Computer Software.iso
/
snws190s.zip
/
ARTICLE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-21
|
23KB
|
869 lines
/*
SNEWS 1.90
news - routines to read and display an article
Copyright (C) 1991 John McCombs, Christchurch, NEW ZEALAND
john@ahuriri.gen.nz
PO Box 2708, Christchurch, NEW ZEALAND
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 1, as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the file COPYING, which contains a copy of the GNU General
Public License.
*/
#include "defs.h"
#include "snews.h"
#include <alloc.h>
#include <io.h>
#include <ctype.h>
int xfile2 = FALSE;
void ReplyAddress(TEXT *tx, char *subject);
/*------------------------- read in an article -----------------------------*/
TEXT *load_article(char *fnx, long offset)
{
/*
* Open the file and read it. Save the author and organisation
* fill in the structures
*/
FILE *tmp_file;
char buf[256], lnbuf[256], *p, *s;
TEXT *tx;
LINE *ln, *lz;
int ct, i;
tx = NULL;
ct = 0;
if ((tmp_file = fopen(fnx, "rb")) != NULL) {
fseek(tmp_file, offset, SEEK_SET);
tx = xmalloc(sizeof(TEXT));
tx->top = NULL;
tx->start = NULL;
strcpy(tx->follow_up, "");
strcpy(tx->author, " ** none ** ");
strcpy(tx->organisation, " ** none ** ");
while (fgets(buf, 255, tmp_file) != NULL) {
if (strncmp(buf, "@@@@END", 7) == 0) break;
expand_tabs(buf, 255);
/*
* We now have a line of input. If the line is two long
* it is wrapped at spaces or '!'. The lines of text are
* stored in LINE structures
*/
p = &buf[0];
while (strlen(p) > 0) {
strcpy(lnbuf, p);
if (strlen(p) <= 80) {
strcpy(lnbuf, p);
*p = '\x00';
} else {
p += 79;
for (i = 79; i > 50; i--) {
if ((lnbuf[i] == ' ') || (lnbuf[i] == '!'))
break;
p--;
}
lnbuf[i] = '\x00';
}
/* is it the first line - if so int the TEXT structure */
if (ct == 0) {
ln = xmalloc(sizeof(LINE));
ln->last = NULL;
tx->top = ln;
} else {
lz = ln;
ln->next = xmalloc(sizeof(LINE));
ln = ln->next;
ln->last = lz;
}
lnbuf[79] = '\x00';
ln->index = ct;
strcpy(ln->data, lnbuf);
if ((strlen(lnbuf) == 1) && (tx->start == NULL))
tx->start = ln;
ct++;
/* save the header info */
if ((tx->start == NULL) && (strncmp("From:", lnbuf, 5) == 0)) {
s = lnbuf + 5;
while (*s && isspace(*s)) s++;
*(s + WHO_LENGTH - 1) = '\0';
strcpy(tx->author, s);
}
if ((tx->start == NULL) && ((strncmp("Organisation:", lnbuf, 13) == 0) || (strncmp("Organization:", lnbuf, 13) == 0))) {
s = lnbuf + 13;
while (*s && isspace(*s)) s++;
*(s + ORG_LENGTH - 1) = '\0';
strcpy(tx->organisation, s);
}
if ((tx->start == NULL) && (strncmp("Followup-To:", lnbuf, 12) == 0)) {
s = lnbuf + 12;
while (*s && isspace(*s)) s++;
*(s + 80 - 1) = '\0';
strcpy(tx->follow_up, s);
}
}
}
ln->next = NULL;
tx->lines = ct;
fclose(tmp_file);
}
return(tx);
}
/*---------------------- deallocate article memory ------------------------*/
void free_article(TEXT *t)
{
LINE *l, *k;
l = t->top;
while (l != NULL) {
k = l;
l = l->next;
free(k);
}
free(t);
}
/*---------------------------- read an article ----------------------------*/
int read_article(ACTIVE *gp, TEXT *tx, char *subject, int a_ct, int of_ct)
{
/*
* This routine alloas the user to read an article
*/
LINE *this, *tmp; /* current thread */
int exit_code; /* why we are exiting the loop */
char sub_tmp[80];
int ch, i;
this = tx->start;
exit_code = 0;
show_article(gp, tx, subject, this, a_ct, of_ct);
while ((exit_code == 0) || (exit_code == EX_DUMMY)) {
exit_code = 0;
gotoxy(1,25);
ch = getch();
switch (ch) {
case 0 :
ch = getch();
switch (ch) {
case Fn1 :
show_help(HELP_ARTICLES);
break;
case Fn2 :
show_values();
break;
case UP_ARR :
if (this->last != NULL) {
this = this->last;
gotoxy(1,TEXT_LINE+PAGE_LENGTH-1);
delline();
gotoxy(1,TEXT_LINE);
insline();
clreol();
cputs(this->data);
}
exit_code = EX_DUMMY;
break;
case DN_ARR :
if (this->next != NULL) {
this = this->next;
gotoxy(1,TEXT_LINE);
delline();
gotoxy(1,TEXT_LINE+PAGE_LENGTH-1);
insline();
tmp = this;
for (i = 0; i < PAGE_LENGTH-1; i++) {
if (tmp == NULL) break;
tmp = tmp->next;
}
clreol();
if (tmp == NULL) {
cputs(" ");
} else {
cputs(tmp->data);
}
}
exit_code = EX_DUMMY;
break;
case PGUP :
for (i = 0; i < PAGE_LENGTH-1; i++) {
if (this->last == NULL) break;
this = this->last;
}
break;
case PGDN :
for (i = 0; i < PAGE_LENGTH-1; i++) {
if (this->next == NULL) break;
this = this->next;
}
break;
case HOME :
this = tx->start;
break;
case END :
this = tx->start;
while (this->next != NULL)
this = this->next;
break;
case LEFT :
exit_code = LEFT;
break;
case RIGHT :
exit_code = RIGHT;
break;
default :
exit_code = EX_DUMMY;
break;
}
break;
case 'p' :
strcpy(sub_tmp, "");
post(NULL, gp->group, sub_tmp);
break;
case 'f' :
if (strcmp(tx->follow_up, "") == 0)
post(tx, gp->group, subject);
else
post(tx, tx->follow_up, subject);
break;
case 'r' :
reply_to_article(tx, subject);
break;
case 'R' :
ReplyAddress(tx, subject);
break;
case 'm' :
mail_to_someone(tx);
break;
case 's' :
save_to_disk(tx);
message("-- Done --");
break;
case 'w' :
xfile2 = TRUE;
save_to_disk(tx);
xfile2 = FALSE;
message("--Done --");
break;
case 'x' :
rot13(tx);
break;
case '?' :
case 'h' :
show_help(HELP_ARTICLES);
break;
case TAB :
exit_code = EX_NEXT_UNREAD;
break;
case ENTER :
exit_code = EX_NEXT;
break;
case ESCAPE :
exit_code = EX_QUIT;
break;
default :
exit_code = EX_DUMMY;
break;
} /* note, there was a ';' here */
if (exit_code == 0)
show_article(gp, tx, subject, this, a_ct, of_ct);
}
return(exit_code);
}
/*-------------------- show the list of active groups -----------------------*/
void show_article(ACTIVE *gp, TEXT *tx, char *subject, LINE *this, int a_ct,
int of_ct)
{
/*
* This routine show a page of an article
*/
int i;
char buf[60];
clrscr();
strcpy(buf, subject);
buf[49] = '\x00';
textbackground(headb); textcolor(headf);
clreol();
cprintf("Group: %-30s Article: %2d of %2d\r\n",
gp->group, a_ct, of_ct);
clreol();
cprintf("Subject: %-50s %4d lines\r\n", buf, tx->lines);
clreol();
/* cprintf("From: %s; %s", tx->author, tx->organisation);*/
cprintf("From: %s", tx->author);
textbackground(textb); textcolor(textf);
gotoxy(1, TEXT_LINE);
for (i = 0; i < PAGE_LENGTH; i++) {
gotoxy(1, i+TEXT_LINE);
cputs(this->data);
this = this->next;
if (this == NULL) break;
}
command("ESC=select thread TAB=next unread ENTER=next F1 or '?'=help");
}
/*-------------------------- save article --------------------------------*/
void save_to_disk(TEXT *tx)
{
/*
* This routine saves an article to disk, appending if necessary
*/
FILE *tmp = NULL;
LINE *ln;
char fn[80];
int ch;
if (xfile2 == TRUE) {
strcpy(fn,"\\extract.nws");
} else {
message("Enter filename? ");
gets(fn);
}
if (access(fn, 0) == 0) {
if (xfile2 == TRUE) {
if ((tmp = fopen(fn, "at")) == NULL) {
message("*** Cannot open file for appending - "
"press any key to continue ***");
getch();
}
} else {
message("File exists - append(y/n)? ");
while (((ch = getch()) != 'y') && (ch != 'n'));
if (ch == 'y') {
if ((tmp = fopen(fn, "at")) == NULL) {
message("*** Cannot open file for appending - "
"press any key to continue ***");
getch();
}
}
}
} else {
if ((tmp = fopen(fn, "wt")) == NULL) {
message("*** Cannot open file for output - press a key to continue ***");
getch();
}
}
if (tmp != NULL) {
if (xfile2 == TRUE) {
fputs("\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\n",tmp);
}
ln = tx->top;
while (ln != NULL) {
fputs(ln->data, tmp);
ln = ln->next;
}
fclose(tmp);
}
}
/*-------------------------- reply to article ---------------------------*/
void reply_to_article(TEXT *tx, char *subject)
{
/*
* Mail reply to article
*/
#ifdef INCLUDE_SIG
FILE *sig;
char sig_fn[80];
#endif
FILE *tmp;
LINE *ln;
int ch;
char fn[80];
char buf[256];
char author[80], msg_id[80];
strcpy(fn, "reply.tmp");
if ((tmp= fopen(fn, "wt")) != NULL) {
strcpy(author, " ");
get_his_stuff(tx, author, msg_id);
/* add the quoted message */
message("Quote article (y/n)? ");
while (((ch = getch()) != 'y') && (ch != 'n'));
if (ch == 'y') {
fprintf(tmp, "\nIn article %s you write:\n\n", msg_id);
ln = tx->start;
while (ln != NULL) {
fprintf(tmp, " > %s", ln->data);
ln = ln->next;
}
}
#ifdef INCLUDE_SIG
/* append the signature if there is one */
strcpy(sig_fn, my_stuff.home);
strcat(sig_fn, my_stuff.signature);
if ((sig= fopen(sig_fn, "rt")) != NULL) {
fprintf(tmp, "\n--\n");
while (fgets(buf, 79, sig) != NULL)
fputs(buf, tmp);
}
fclose(sig);
#endif
fclose(tmp);
ch = 'e';
/* NEW BIT includes send/abort/edit */
while ((ch != 's') && (ch != 'a')) {
if (ch == 'e') {
sprintf(buf, my_stuff.editor, fn);
system(buf);
}
clrscr();
gotoxy(1,23);
cprintf(" Mail reply addressed to: %s",author);
sprintf(buf,"Mail reply: (S)end, (A)bort, or (E)dit again? (S/A/E):");
message(buf);
while (((ch = getch()) != 's') && (ch != 'a') && (ch != 'e'));
gotoxy(1,24);
}
if (ch == 's') {
sprintf(buf, "mail -s \"Re: %s\" %s <%s", subject, author, fn);
system(buf);
}
unlink(fn);
message("-- Press any key to continue --");
getch();
} else {
message("*** Cannot open temp file - press any key to continue ***");
getch();
}
}
/* ---------- (R)eply allowing specified address or alias ---------------- */
void ReplyAddress(TEXT *tx, char *subject)
{
#ifdef INCLUDE_SIG
FILE *sig;
char sig_fn[80];
#endif
FILE *tmp;
FILE *alias;
LINE *ln;
int ch;
char *s;
char fn[80];
char buf[256];
char author[80], msg_id[80];
strcpy(fn, "reply.tmp");
if ((tmp= fopen(fn, "wt")) != NULL) {
get_his_stuff(tx, author, msg_id);
/* add the quoted message */
message("Quote article (y/n)? ");
while (((ch = getch()) != 'y') && (ch != 'n'));
if (ch == 'y') {
fprintf(tmp, "\nIn article %s you write:\n\n", msg_id);
ln = tx->start;
while (ln != NULL) {
fprintf(tmp, " > %s", ln->data);
ln = ln->next;
}
}
#ifdef INCLUDE_SIG
/* append the signature if there is one */
strcpy(sig_fn, my_stuff.home);
strcat(sig_fn, my_stuff.signature);
if ((sig= fopen(sig_fn, "rt")) != NULL) {
fprintf(tmp, "\n--\n");
while (fgets(buf, 79, sig) != NULL)
fputs(buf, tmp);
}
fclose(sig);
#endif
fclose(tmp);
sprintf(buf, "Send reply to who (aliases allowed): ");
message(buf);
gets(author);
if ((alias = fopen(my_stuff.alias_file,"rt")) != NULL) {
while (fgets(buf, 255, alias)!=NULL) {
if (buf[0] == ';' || isspace(buf[0]))
continue;
if (strnicmp(author,buf,strlen(author)) == 0) {
s = strchr(buf,' ');
while (*s && isspace(*s)) s++;
s = strtok(s, " ;\t\r\n");
strcpy(author,s);
break;
}
}
fclose(alias);
}
ch = 'e';
while ((ch != 's') && (ch != 'a')) {
if (ch == 'e') {
sprintf(buf, my_stuff.editor, fn);
system(buf);
}
sprintf(buf,"Mail article: (S)end, (A)bort, or (E)dit again? (S/A/E):");
message(buf);
while (((ch = getch()) != 's') && (ch != 'a') && (ch != 'e'));
gotoxy(1,24);
}
if (ch == 's') {
sprintf(buf, "mail -s \"%s\" %s <%s", subject, author, fn);
system(buf);
}
unlink(fn);
message("-- Press any key to continue --");
getch();
} else {
message("*** Cannot open temp file - press any key to continue ***");
getch();
}
}
/*-------------------------- reply to article ---------------------------*/
void mail_to_someone(TEXT *tx)
{
/*
* Mail this article to someone
*/
FILE *tmp;
LINE *ln;
int ch;
char fn[80];
char buf[256], who[80];
char author[80], msg_id[80];
strcpy(fn, "reply.tmp");
if ((tmp= fopen(fn, "wt")) != NULL) {
get_his_stuff(tx, author, msg_id);
/* add the quoted message */
command("");
lmessage("Who do you want to mail this article to? ");
gets(who);
fprintf(tmp, "\nThis article was forwarded to you by %s@%s (%s):\n\n",
my_stuff.user, my_stuff.my_domain, my_stuff.my_name);
fprintf(tmp,"--------------------------------- cut here -----------------------------\n\n");
ln = tx->top;
while (ln != NULL) {
fprintf(tmp, "%s", ln->data);
ln = ln->next;
}
fprintf(tmp,"--------------------------------- cut here -----------------------------\n\n");
fclose(tmp);
sprintf(buf, "Send message to %s (y/n)? ", who);
message(buf);
while (((ch = getch()) != 'y') && (ch != 'n'));
if (ch == 'y') {
sprintf(buf, "mail %s <%s", who, fn);
system(buf);
}
unlink(fn);
message("-- Press any key to continue --");
getch();
} else {
message("*** Cannot open temp file - press any key to continue ***");
getch();
}
}
/*----------------------- find email address in line --------------------*/
/*---------------------------------------------------------*/
/* char *get_address() */
/* */
/* searches for the '@' char in internet addresses and */
/* then extracts the word the '@' is in. The terminat- */
/* ating characters are : ':' '<' '>' '(' ')' '"' '\t' */
/* '\r' and '\n'; at which point it stops looking. */
/* */
/*---------------------------------------------------------*/
char *get_address(char *buf, char *addr)
{
char *p , *c;
/* search for the '@' or "at" that is in every internet address */
if ((p = strchr(buf,'@')) != NULL) {
c = p;
while (*p && (*p != ' ' &&
*p != '\t' &&
*p != ':' &&
*p != '<' &&
*p != '\"' &&
*p != '(' )) {
/* quite a few cases to check for */
p--;
}
while (*c && (*c != ' ' &&
*c != '\t' &&
*c != ':' &&
*c != '>' &&
*c != '\"' &&
*c != '\n' &&
*c != '\r' &&
*c != ')' )) {
/* quite a few cases to check for */
c++;
}
*c = '\0';
strcpy(addr, ++p);
return addr;
}
return NULL;
}
/*----------------------- get stuff off article header --------------------*/
/*---------------------------------------------------------*/
/* void get_his_stuff() */
/* */
/* obtains the address of the person in the passed arti- */
/* cle, as well as the msgid. */
/* */
/*---------------------------------------------------------*/
void get_his_stuff(TEXT *tx, char *author, char *msg_id)
{
/*
* Retrieve the author and msg_id from the article
*/
LINE *ln;
char *p;
char buf[256];
char *null_name = {" < no name > "};
strcpy(author, null_name);
strcpy(msg_id, " <none> ");
ln = tx->top;
while (ln != NULL) {
strcpy(buf, ln->data);
p = strtok(buf, " :\n\r");
p = strtok(NULL, " :\n\r");
if (strnicmp(ln->data, "Message-ID:", 11) == 0) {
p = ln->data + 11;
while (*p && isspace(*p)) p++;
p = strtok(p, " :\n\r");
if (p)
strcpy(msg_id, p);
else
strcpy(msg_id, ln->data + 11);
}
if ((strnicmp(ln->data, "From:", 5) == 0) && (strcmp(author, null_name) == 0)) {
if (get_address(ln->data, author) == NULL) {
strcpy(author, p);
}
}
if (strnicmp(ln->data, "Reply-To:", 5) == 0) {
if (get_address(ln->data, author) == NULL) {
strcpy(author, p);
}
}
if (strlen(ln->data) < 2) break;
ln = ln->next;
}
}
/*--------------------------- rot 13 the article ------------------------*/
void rot13(TEXT *tx)
{
LINE *ln;
int i, c;
ln = tx->start;
while (ln != NULL) {
for (i = 0; i < strlen(ln->data); i++) {
c = *((ln->data)+i);
if ((c >= 'A') && (c <= 'Z')) {
*((ln->data)+i) = (((c-'A') + 13) % 26) + 'A';
} else {
if ((c >= 'a') && (c <= 'z')) {
*((ln->data)+i) = (((c-'a') + 13) % 26) + 'a';
}
}
}
ln = ln->next;
}
}
/*--------------------------- expand the tabs ----------------------------*/
void expand_tabs(char *buf, int max_len)
{
int l, k;
char tmp[256], *p, *t;
p = buf;
t = &tmp[0];
l = 0;
while ((*p != '\x00') && (l < max_len)) {
if (*p != '\x09') {
*t = *p;
t++;
p++;
l++;
} else {
p++;
k = ((l / 8) + 1) * 8;
for ( ; l < k ; l++) {
*t = ' ';
t++;
if (l >= max_len) break;
}
}
}
*t = '\x00';
strcpy(buf, tmp);
}